Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[State Management] State containers improvements #54436

Conversation

Dosant
Copy link
Contributor

@Dosant Dosant commented Jan 10, 2020

Summary

Some maintenance and minor fixes to state containers based on experience while working with them in #53582

  1. Patch unit tests to use current "terminology" (e.g. "transition" vs "mutation")
  2. Fix docs where "store" was used instead of "state container"
  3. Allow to create state container without transition.
  4. Fix freeze function to deeply freeze objects.
  5. Restrict State to BaseState with extends object.
  6. in set() function, make sure the flow goes through dispatch to make sure middleware see this update
  7. Improve type inference for useTransition()
  8. Improve type inference for createStateContainer().

Other issues I noticed, but didn't fix in reasonable time:

  1. Can't use addMiddleware without explicit type casting [State Management] State containers and redux middlewares types mismatch #54438
  2. Transitions and Selectors allow any state, not bind to container's state [State Management] Transitions and selectors should know about state shape #54439

Checklist

Use strikethroughs to remove checklist items you don't feel are applicable to this PR.

For maintainers

@@ -35,7 +35,7 @@ export const createStateContainerReactHelpers = <Container extends StateContaine
return value;
};

const useTransitions = () => useContainer().transitions;
const useTransitions: () => Container['transitions'] = () => useContainer().transitions;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -9,7 +9,7 @@
```ts
import { createStateContainer, createStateContainerReactHelpers } from 'src/plugins/kibana_utils';

const container = createStateContainer({}, {});
const container = createStateContainer({});
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seemed to be reasonable to also make transitions optional. Just like selectors

defaultState: State,
pureTransitions: PureTransitions
): ReduxLikeStateContainer<State, PureTransitions>;
export function createStateContainer<
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not exactly sure, but I ended up adding overrides here because bumped into following with previous setup just with optional generics:

const container = createStateContainer({test: 'test}, {action: (s) => () => s}); 
container.get().test // ts works
container.transitions.action() // ts works 

but
explicitly specify only State shape in generic:

type S = {test: string};
const container = createStateContainer<S>({test: 'test}, {action: (s) => () => s}); 
container.get().test // ts works
container.transitions.action() // doesn't work.. ts now think, that transitions are {}. 

So adding those overrides instead of using optional generic params just made it explicit, that when generic params are specified explicitly - the number of specified params have to match number of arguments.

@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-app-arch (Team:AppArch)

@Dosant Dosant added the release_note:skip Skip the PR/issue when compiling release notes label Jan 10, 2020
@@ -56,9 +74,13 @@ export const createStateContainer = <
state$,
getState: () => data$.getValue(),
set: (state: State) => {
data$.next(freeze(state));
container.dispatch({ type: $$setActionType, args: [state] });
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this makes set() to go through dispatch and not be skipped by added middlewares

Copy link
Contributor

@streamich streamich left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code LGTM. Just see one comment about BaseState.

src/plugins/kibana_utils/public/state_containers/types.ts Outdated Show resolved Hide resolved
@Dosant
Copy link
Contributor Author

Dosant commented Jan 10, 2020

I would not use Record<string, any> as that means state is basically any object, because key is any string and values of those keys are any. Maybe object can work here.

@streamich, Please see: #54436 (comment)
I would really appreciate another pair of eyes looking at it.

import { encode } from 'rison-node'
export function encodeFn<S extends object>(s: S) {
  encode(s); // error
}
import { encode } from 'rison-node'
export function encodeFn<S extends Record<string: any>>(s: S) {
  encode(s); // works
}

The error is:

TS2345: Argument of type 'S' is not assignable to parameter of type 'RisonValue'.   
Type 'object' is not assignable to type 'RisonValue'.     
Type 'object' is not assignable to type 'RisonArray'.       
Type 'S' is not assignable to type 'RisonArray'.         
Type '{}' is missing the following properties from type 'RisonArray': length, pop, push, concat, and 28 more.

@streamich
Copy link
Contributor

streamich commented Jan 10, 2020

Record<string, any> "works" because Record<string, any> is almost the same as anyRecord<string ... means that it is an object with all possible keys of type string (basically meaning any key is allowed) and Record<..., any> means that those keys can contain any value. And when you say ... extends Record<string, any> it basically forces user to make the type of their state to be an object with all possible string keys being valid and to each of those keys it is valid to assign anything. It is very similar to ... extends any.

In your RISON example you probably need to cast the object, maybe something like this

encode(s as RisonValue);

@Dosant
Copy link
Contributor Author

Dosant commented Jan 10, 2020

@streamich, used object.

In your RISON example you probably need to cast the object, maybe something like this

encode(s as RisonValue);

Looks like it :(

…agement/state-containers-improvements

# Conflicts:
#	src/plugins/kibana_utils/public/state_containers/create_state_container.test.ts
#	src/plugins/kibana_utils/public/state_containers/create_state_container.ts
#	src/plugins/kibana_utils/public/state_containers/create_state_container_react_helpers.test.tsx
#	src/plugins/kibana_utils/public/state_containers/create_state_container_react_helpers.ts
#	src/plugins/kibana_utils/public/state_containers/types.ts
@Dosant Dosant added the review label Jan 13, 2020
@Dosant Dosant marked this pull request as ready for review January 13, 2020 05:47
@Dosant Dosant requested a review from a team as a code owner January 13, 2020 05:47
@Dosant
Copy link
Contributor Author

Dosant commented Jan 13, 2020

@elasticmachine merge upstream

@kibanamachine
Copy link
Contributor

💚 Build Succeeded

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

@Dosant Dosant added v7.6.0 and removed v7.7.0 labels Jan 13, 2020
@Dosant Dosant merged commit a899df3 into elastic:master Jan 13, 2020
Dosant added a commit to Dosant/kibana that referenced this pull request Jan 13, 2020
Some maintenance and minor fixes to state containers based on experience while working with them in elastic#53582

Patch unit tests to use current "terminology" (e.g. "transition" vs "mutation")
Fix docs where "store" was used instead of "state container"
Allow to create state container without transition.
Fix freeze function to deeply freeze objects.
Restrict State to BaseState with extends object.
in set() function, make sure the flow goes through dispatch to make sure middleware see this update
Improve type inference for useTransition()
Improve type inference for createStateContainer().

Other issues noticed, but didn't fix in reasonable time:
Can't use addMiddleware without explicit type casting elastic#54438
Transitions and Selectors allow any state, not bind to container's state elastic#54439
Dosant added a commit that referenced this pull request Jan 13, 2020
Some maintenance and minor fixes to state containers based on experience while working with them in #53582

Patch unit tests to use current "terminology" (e.g. "transition" vs "mutation")
Fix docs where "store" was used instead of "state container"
Allow to create state container without transition.
Fix freeze function to deeply freeze objects.
Restrict State to BaseState with extends object.
in set() function, make sure the flow goes through dispatch to make sure middleware see this update
Improve type inference for useTransition()
Improve type inference for createStateContainer().

Other issues noticed, but didn't fix in reasonable time:
Can't use addMiddleware without explicit type casting #54438
Transitions and Selectors allow any state, not bind to container's state #54439
jloleysens added a commit to jloleysens/kibana that referenced this pull request Jan 13, 2020
…age-offset-floating-tooltip

* 'master' of github.com:elastic/kibana:
  [Maps] refactor isPointsOnly, isLinesOnly, and isPolygonsOnly to make synchronous (elastic#54067)
  Fix icon path in tutorial introduction (elastic#49684)
  [State Management] State containers improvements (elastic#54436)
  Fix floating tools rendering logic (elastic#54505)
  Handle another double quote special case (elastic#54474)
  [Home][Tutorial] Add data UI for IBM MQ Filebeat module (elastic#54238)
  fix(package): upgrade transitive dependency elliptic to v6.5.2 (elastic#54476)
  [Graph] Fix various a11y issues (elastic#54097)

# Conflicts:
#	src/legacy/core_plugins/console/public/np_ready/application/models/legacy_core_editor/legacy_core_editor.ts
chrisronline pushed a commit to chrisronline/kibana that referenced this pull request Jan 13, 2020
Some maintenance and minor fixes to state containers based on experience while working with them in elastic#53582

Patch unit tests to use current "terminology" (e.g. "transition" vs "mutation")
Fix docs where "store" was used instead of "state container"
Allow to create state container without transition.
Fix freeze function to deeply freeze objects.
Restrict State to BaseState with extends object.
in set() function, make sure the flow goes through dispatch to make sure middleware see this update
Improve type inference for useTransition()
Improve type inference for createStateContainer().

Other issues noticed, but didn't fix in reasonable time:
Can't use addMiddleware without explicit type casting elastic#54438
Transitions and Selectors allow any state, not bind to container's state elastic#54439
jkelastic pushed a commit to jkelastic/kibana that referenced this pull request Jan 17, 2020
Some maintenance and minor fixes to state containers based on experience while working with them in elastic#53582

Patch unit tests to use current "terminology" (e.g. "transition" vs "mutation")
Fix docs where "store" was used instead of "state container"
Allow to create state container without transition.
Fix freeze function to deeply freeze objects.
Restrict State to BaseState with extends object.
in set() function, make sure the flow goes through dispatch to make sure middleware see this update
Improve type inference for useTransition()
Improve type inference for createStateContainer().

Other issues noticed, but didn't fix in reasonable time:
Can't use addMiddleware without explicit type casting elastic#54438
Transitions and Selectors allow any state, not bind to container's state elastic#54439
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature:StateManagement release_note:skip Skip the PR/issue when compiling release notes review v7.6.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants